package net.seabook.games.tetris.model;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

public abstract class Piece {
	private List<Tile> blocks = new ArrayList<Tile>();
	private TetrisBoard board;

	private boolean isDead = false;

	private boolean isRotated = false;

	private RotateDirection rDirection = RotateDirection.LEFT;

	public Piece() {
	}
	
	public void drawSelf(Graphics g) {
		// render
		for (Tile block : getBlocks()) {
			block.drawSelf(g);
		}
	}

	public void rotatePiece() {
		if (isRotatable()) {
			rotate();
		}
	}

	public abstract void rotate();

	public boolean isRotateOutofBound(int x) {
		if (x < 0 || x >= TetrisBoard.BOARD_WIDTH) {
			return true;
		}
		return false;
	}

	private boolean isRotatable() {
		for (Tile tile : blocks) {
			int x = tile.getX() / Tile.WIDTH - 1;
			int y = tile.getY() / Tile.HEIGHT;
			
			if (y < 0) {
				return false;
			}

			if (x > 0 && y > 0 && board.getBoard()[x][y]) {
				return false;
			}

			x = tile.getX() / Tile.WIDTH + 1;
			y = tile.getY() / Tile.HEIGHT;

			if (x < TetrisBoard.BOARD_GRID_WIDTH
					&& y < TetrisBoard.BOARD_GRID_HEIGHT
					&& board.getBoard()[x][y]) {
				return false;
			}
		}
		return true;
	}

	/*
	 * private boolean isRightRotatable() { for (Tile tile : blocks) { if
	 * (tile.getX() + Tile.WIDTH > TetrisBoard.BOARD_WIDTH) { return false; }
	 * int x = tile.getX() / Tile.WIDTH + 1; int y = tile.getY() / Tile.HEIGHT;
	 * 
	 * if (x < TetrisBoard.BOARD_GRID_WIDTH && y < TetrisBoard.BOARD_GRID_HEIGHT
	 * && board.getBoard()[x][y]) { return false; } } return true; }
	 */

	private boolean isLeftMovable() {
		for (Tile tile : blocks) {
			int x = tile.getX() / Tile.WIDTH - 1;
			int y = tile.getY() / Tile.HEIGHT;
			if (tile.getX() <= 0)
				return false;
			if (x > 0 && y > 0 && board.getBoard()[x][y]) {
				return false;
			}
		}
		return true;
	}

	private boolean isRightMovable() {
		for (Tile tile : blocks) {
			int x = tile.getX() / Tile.WIDTH + 1;
			int y = tile.getY() / Tile.HEIGHT;
			if (tile.getX() + Tile.WIDTH >= TetrisBoard.BOARD_WIDTH)
				return false;
			if (x > 0 && y > 0 && board.getBoard()[x][y]) {
				return false;
			}
		}
		return true;
	}

	private boolean touchedDown() {
		for (Tile tile : blocks) {

			int x = tile.getX() / Tile.WIDTH;
			int y = tile.getY() / Tile.HEIGHT + 1;

			if (tile.getY() + Tile.HEIGHT >= TetrisBoard.BOARD_HEIGHT) {
				isDead = true;
				return true;
			}

			if (x >= 0 && y > 0 && board.getBoard()[x][y]) {
				isDead = true;
				return true;
			}

		}
		return false;
	}

	public void moveDown() {
		if (touchedDown()) {
			for (Tile piece : blocks) {
				int x = piece.getX() / Tile.WIDTH;
				int y = piece.getY() / Tile.HEIGHT;
				this.board.setFilledTileColor(piece.getFilledColor());
				updateBoard(x, y);
			}
			
		//	TetrisHelper.printBoardStatus(board);
			
			for (int j = TetrisBoard.BOARD_GRID_HEIGHT - 1; j >= 0; j--) {
				if (board.isTheLineFull(j)) {
					board.getFullLineNo().add(j);
				}
			}
			
			board.resetBoard();
		} else {
			for (Tile piece : blocks) {
				piece.setY(piece.getY() + Tile.HEIGHT);
			}
		}
	}

	private void updateBoard(int x, int y) {
		board.getBoard()[x][y] = true;
	}

	public void dipose() {
		blocks.clear();
	}

	public void moveLeft() {
		if (isLeftMovable()) {
			for (Tile piece : blocks) {
				piece.setX(piece.getX() - Tile.WIDTH);
			}
		}
	}

	public void moveRight() {
		if (isRightMovable()) {
			for (Tile piece : blocks) {
				piece.setX(piece.getX() + Tile.WIDTH);
			}
		}
	}
	
	public void setPieceColor(Color color) {
		for (Tile tile : blocks) {
			tile.setFilledColor(color);
		}
	}

	public boolean isRotated() {
		return isRotated;
	}

	public void setRotated(boolean isRotated) {
		this.isRotated = isRotated;
	}

	public RotateDirection getrDirection() {
		return rDirection;
	}

	public void setrDirection(RotateDirection rDirection) {
		this.rDirection = rDirection;
	}

	public List<Tile> getBlocks() {
		return blocks;
	}

	public void setBlocks(List<Tile> blocks) {
		this.blocks = blocks;
	}

	public TetrisBoard getBoard() {
		return board;
	}

	public void setBoard(TetrisBoard board) {
		this.board = board;
	}

	public boolean isDead() {
		return isDead;
	}

	public void setDead(boolean isDead) {
		this.isDead = isDead;
	}

}
